# Python 趣味编程：第 12 章
# 练习问题 12.2 例題 6.4 球在箱子里的移动
# --------------------------
# 程序名: ex12-bouncing-blit.py

import pygame
from dataclasses import dataclass
import random

WIDTH = 640
HEIGHT = 320

# 颜色的定义
GREEN = (0, 255, 0)
BK_COLOR = GREEN   # 背景色的设置

FPS = 60     # Frame per Second每秒帧数

@dataclass
class Ball:
    x: int
    y: int
    dx: int
    dy: int
    vx: int
    vy: int
    image: pygame.Surface

    def move(self):
        self.x += self.vx
        self.y += self.vy 

    def draw(self, to_image):
        to_image.blit(self.image, (self.x, self.y))

@dataclass
class Box:
    west: int
    north: int
    east: int
    south: int
    def __init__(self, x, y, w, h):
        self.west, self.north = (x, y)
        self.east, self.south = (x + w, y + h)

    def check_wall(self, ball):
        if ball.x <= self.west or ball.x + ball.dx >= self.east:
            ball.vx = -ball.vx
        if ball.y <= self.north or ball.y + ball.dy >= self.south:
            ball.vy = -ball.vy

    def set_ball(self):
        image = pygame.image.load("ball.png").convert()   # 读取球图像
        image.set_colorkey(image.get_at((0, 0)))
        rect = image.get_rect()
        dx, dy = (rect.width, rect.height)
        # 随机数化初始位置:防止生成在墙内
        ball_x = random.randint(self.west + 1, self.east - dx - 1)
        ball_y = random.randint(self.north + 1, self.south - dy - 1)
        self.ball = Ball(ball_x, ball_y, dx, dy, 
                         random.randint(2, 8), random.randint(2, 8), image)

    def animate(self):
        loop = True
        screen.fill(BK_COLOR)  
        while loop: # 无限循环
            for event in pygame.event.get():
                # 处理“关闭”按钮
                if event.type == pygame.QUIT: loop = False
            clock.tick(FPS)      # 根据每秒的呼叫次数延迟
            self.ball.move()
            self.check_wall(self.ball)
            self.ball.draw(screen)
            pygame.display.flip()   # 把绘图内容反映在画面上
            screen.fill(BK_COLOR)  

# ---------------------------------------
screen = pygame.display.set_mode((WIDTH, HEIGHT)) # 准备screen
clock = pygame.time.Clock()   # 时钟对象
draw = pygame.draw

box = Box(0, 0, WIDTH, HEIGHT) # 盘面的初始化
box.set_ball()                 # 生成球
box.animate()                  # 主程序
pygame.quit()                  # 关闭画面
